using System;

namespace StevensReceipts.Repository.Migrations
{
    using System.Collections.Generic;
    using System.Data.Entity.Migrations;
    using StevensReceipts.Domain;

    internal sealed class Configuration : DbMigrationsConfiguration<ReceiptsDbContext>
    {
        public Configuration()
        {
            AutomaticMigrationsEnabled = true;
        }



        protected override void Seed(ReceiptsDbContext context)
        {
            CreateIndeies(context);
            SeedChartofAccountsRelatedData(context);
        }

        private static void SeedChartofAccountsRelatedData(ReceiptsDbContext context)
        {
            var asserts = new ChartofAccountCategory {Id = 1, Name = "Asserts"};

            var currentAssertAccountType = new ChartofAccountAccountType {Id = 1, Name = "Current Assert"};
            var fixedAssertAccountType = new ChartofAccountAccountType {Id = 2, Name = "Fixed Assert"};
            var nonCurrentAssertAccountType = new ChartofAccountAccountType {Id = 3, Name = "Non-current Assert"};
            var prePaymentAccountType = new ChartofAccountAccountType {Id = 4, Name = "Prepayment"};
            asserts.Types = new List<ChartofAccountAccountType>
                                {
                                    currentAssertAccountType,
                                    fixedAssertAccountType,
                                    nonCurrentAssertAccountType,
                                    prePaymentAccountType
                                };


            var liabilities = new ChartofAccountCategory {Id = 2, Name = "Liabilities"};


            var currentLiabilityAccountType = new ChartofAccountAccountType {Id = 5, Name = "Current Liability"};
            var liabilityAccountType = new ChartofAccountAccountType {Id = 6, Name = "Liability"};
            var nonCurrentLiabilityAccountType = new ChartofAccountAccountType {Id = 7, Name = "Non-current Liability"};
            liabilities.Types = new List<ChartofAccountAccountType>
                                    {
                                        currentLiabilityAccountType,
                                        liabilityAccountType,
                                        nonCurrentLiabilityAccountType
                                    };


            var expenses = new ChartofAccountCategory {Id = 3, Name = "Expenses"};

            var depreciationAccountType = new ChartofAccountAccountType {Id = 8, Name = "Depreciation"};
            var directCostsAccountType = new ChartofAccountAccountType {Id = 9, Name = "Direct Costs"};
            var expenseAccountType = new ChartofAccountAccountType {Id = 10, Name = "Expense"};
            var overheadAccountType = new ChartofAccountAccountType {Id = 11, Name = "Overhead"};

            expenses.Types = new List<ChartofAccountAccountType>
                                 {
                                     depreciationAccountType,
                                     directCostsAccountType,
                                     expenseAccountType,
                                     overheadAccountType
                                 };


            var equity = new ChartofAccountCategory {Id = 4, Name = "Equity"};

            var equityAccountType = new ChartofAccountAccountType {Id = 12, Name = "Equity"};
            equity.Types = new List<ChartofAccountAccountType> {equityAccountType};


            var revenue = new ChartofAccountCategory {Id = 5, Name = "Revenue"};
            var revenueTypes = new List<ChartofAccountAccountType>();

            var otherIncomeAccountType = new ChartofAccountAccountType {Id = 13, Name = "Other Income"};
            var revenueAccountType = new ChartofAccountAccountType {Id = 14, Name = "Revenue"};
            var saleAccountType = new ChartofAccountAccountType {Id = 15, Name = "Sale"};

            revenue.Types = new List<ChartofAccountAccountType>
                                {
                                    otherIncomeAccountType,
                                    revenueAccountType,
                                    saleAccountType
                                };


            context.ChartofAccountCategories.AddOrUpdate(
                asserts,
                liabilities,
                expenses,
                equity,
                revenue
                );


            var tr15E = new TaxRate
                          {
                              Id = 1,
                              Name = "15% GST on Expenses",
                              Rate = 0.15
                          };
            var tr15I = new TaxRate
                          {
                              Id = 2,
                              Name = "15% GST on Income",
                              Rate = 0.15
                          };
            var trI = new TaxRate
                          {
                              Id = 3,
                              Name = "GST on Imports",
                              Rate = 0
                          };
            var trNo = new TaxRate
                          {
                              Id = 4,
                              Name = "No GST",
                              Rate = 0
                          };
            var tr0 = new TaxRate
                          {
                              Id = 5,
                              Name = "Zero Rated",
                              Rate = 0
                          };
            context.TaxRates.AddOrUpdate(
                tr0,tr15E,tr15I,trI, trNo);

            Address systemAddress = new Address
                                        {
                                            AddressLine1 = "94 Taumata Road",
                                            Suburb = "Mt Albert",
                                            City = "Auckland",
                                            PostCode = 1025,
                                            Country = "New Zealand"
                                        };

            Business systemBusiness = new Business
                                          {
                                              Id = 1,
                                              BusinessName = "System",
                                              BusinessCountry = "New Zealand",
                                              TradingName = "System",
                                              BusinessLine = "System",
                                              GstRegistered = true,
                                              FinancialYearEndMonth = 3,
                                              FinancialYearEndDay = 31,
                                              GstNumber = "000-000-000",
                                              ContactPerson = "System Administrator",
                                              PhysicalAddress = systemAddress,
                                              PostalAddress = systemAddress
                                          };

            var coaSales = new ChartofAccount
                                          {
                                              Id = 1,
                                              AccountType = revenueAccountType,
                                              TaxRate = tr15I,
                                              Business = systemBusiness,
                                              Code = 200,
                                              Balance = 0,
                                              IsSystemAccount = true,
                                              IsDefaultAccount = true,
                                              Name = "Sales",
                                              Description = "Income from any normal business activity",
                                              TaxReturnPercent = 0
                                          };
            var coaOtherRevenue = new ChartofAccount
                                          {
                                              Id = 2,
                                              AccountType = revenueAccountType,
                                              TaxRate = tr15I,
                                              Business = systemBusiness,
                                              Code = 260,
                                              Balance = 0,
                                              IsSystemAccount = true,
                                              IsDefaultAccount = true,
                                              Name = "Other Revenue",
                                              Description = "Any other income that does not relate to normal business activities and is not recurring",
                                              TaxReturnPercent = 0
                                          };
            var coaInterestIncome = new ChartofAccount
                                     {
                                         Id = 3,
                                         AccountType = revenueAccountType,
                                         TaxRate = tr15I,
                                         Business = systemBusiness,
                                         Code = 270,
                                         Balance = 0,
                                         IsSystemAccount = true,
                                         IsDefaultAccount = true,
                                         Name = "Interest Income",
                                         Description =
                                             "Gross interest income (i.e. before deducting Residential Withholding Tax), such as bank interest",
                                         TaxReturnPercent = 0
                                     };
            var coaAds = new ChartofAccount
                          {
                              Id = 101,
                              AccountType = overheadAccountType,
                              TaxRate = tr15E,
                              Business = systemBusiness,
                              Code = 400,
                              Balance = 0,
                              IsSystemAccount = true,
                              IsDefaultAccount = true,
                              Name = "Advertising",
                              Description = "Expenses incurred for advertising while trying to increase sales",
                              TaxReturnPercent = 0
                          };
            var coaDepre = new ChartofAccount
                            {
                                Id = 102,
                                AccountType = overheadAccountType,
                                TaxRate = trNo,
                                Business = systemBusiness,
                                Code = 416,
                                Balance = 0,
                                IsSystemAccount = true,
                                IsDefaultAccount = true,
                                Name = "Depreciation",
                                Description = "The amount of the asset's cost (based on the useful life) that was consumed during the period",
                                TaxReturnPercent = 0
                            };
            var coaEntertainment = new ChartofAccount
                                    {
                                        Id = 103,
                                        AccountType = overheadAccountType,
                                        TaxRate = tr15E,
                                        Business = systemBusiness,
                                        Code = 420,
                                        Balance = 0,
                                        IsSystemAccount = true,
                                        IsDefaultAccount = true,
                                        Name = "Entertainment",
                                        Description =
                                            "50% of the total expense relating to business-related entertainment. E.g. shouting clients or employees  a drink or a meal etc.",
                                        TaxReturnPercent = 0
                                    };
            var coaGeneral = new ChartofAccount
                              {
                                  Id = 104,
                                  AccountType = overheadAccountType,
                                  TaxRate = tr15E,
                                  Business = systemBusiness,
                                  Code = 429,
                                  Balance = 0,
                                  IsSystemAccount = true,
                                  IsDefaultAccount = true,
                                  Name = "General Expenses",
                                  Description =
                                      "General expenses related to the running of the business. ",
                                  TaxReturnPercent = 0
                              };
            var coaInsurance = new ChartofAccount
                                   {
                                       Id = 105,
                                       AccountType = overheadAccountType,
                                       TaxRate = tr15E,
                                       Business = systemBusiness,
                                       Code = 433,
                                       Balance = 0,
                                       IsSystemAccount = true,
                                       IsDefaultAccount = true,
                                       Name = "Insurance",
                                       Description = "Expenses incurred for insuring the business' assets",
                                       TaxReturnPercent = 0
                                   };
            var coaLPH = new ChartofAccount
                                   {
                                       Id = 106,
                                       AccountType = overheadAccountType,
                                       TaxRate = tr15E,
                                       Business = systemBusiness,
                                       Code = 445,
                                       Balance = 0,
                                       IsSystemAccount = true,
                                       IsDefaultAccount = true,
                                       Name = "Light, Power, Heating",
                                       Description = "Expenses incurred for lighting, powering or heating the premises",
                                       TaxReturnPercent = 0
                                   };
            var coaVehicle = new ChartofAccount
                                   {
                                       Id = 107,
                                       AccountType = overheadAccountType,
                                       TaxRate = tr15E,
                                       Business = systemBusiness,
                                       Code = 449,
                                       Balance = 0,
                                       IsSystemAccount = true,
                                       IsDefaultAccount = true,
                                       Name = "Motor Vehicle Expenses",
                                       Description = "Expenses incurred on the running of company motor vehicles",
                                       TaxReturnPercent = 0
                                   };
            var coaOffice = new ChartofAccount
                                   {
                                       Id = 108,
                                       AccountType = overheadAccountType,
                                       TaxRate = tr15E,
                                       Business = systemBusiness,
                                       Code = 453,
                                       Balance = 0,
                                       IsSystemAccount = true,
                                       IsDefaultAccount = true,
                                       Name = "Office Expenses",
                                       Description = "General expenses related to the running of the business office.",
                                       TaxReturnPercent = 0
                                   };
            var coaRent = new ChartofAccount
                                   {
                                       Id = 109,
                                       AccountType = overheadAccountType,
                                       TaxRate = tr15E,
                                       Business = systemBusiness,
                                       Code = 469,
                                       Balance = 0,
                                       IsSystemAccount = true,
                                       IsDefaultAccount = true,
                                       Name = "Rent",
                                       Description = "The payment to lease a building or area.",
                                       TaxReturnPercent = 0
                                   };
            var coaRepairs = new ChartofAccount
                                   {
                                       Id = 110,
                                       AccountType = overheadAccountType,
                                       TaxRate = tr15E,
                                       Business = systemBusiness,
                                       Code = 473,
                                       Balance = 0,
                                       IsSystemAccount = true,
                                       IsDefaultAccount = true,
                                       Name = "Repairs and Maintenance",
                                       Description = "Expenses incurred on a damaged or run down asset that will bring the asset back to its original condition.",
                                       TaxReturnPercent = 0
                                   };
            var coaPhone = new ChartofAccount
                                   {
                                       Id = 111,
                                       AccountType = overheadAccountType,
                                       TaxRate = tr15E,
                                       Business = systemBusiness,
                                       Code = 489,
                                       Balance = 0,
                                       IsSystemAccount = true,
                                       IsDefaultAccount = true,
                                       Name = "Telephone & Internet",
                                       Description = "Expenditure incurred from any business-related phone calls, phone lines, or internet connections",
                                       TaxReturnPercent = 0
                                   };
            var coaTravelN = new ChartofAccount
                                   {
                                       Id = 112,
                                       AccountType = overheadAccountType,
                                       TaxRate = tr15E,
                                       Business = systemBusiness,
                                       Code = 493,
                                       Balance = 0,
                                       IsSystemAccount = true,
                                       IsDefaultAccount = true,
                                       Name = "Travel - National",
                                       Description = "Expenses incurred from domestic travel which has a business purpose",
                                       TaxReturnPercent = 0
                                   };
            var coaTravelI = new ChartofAccount
                                   {
                                       Id = 113,
                                       AccountType = overheadAccountType,
                                       TaxRate = trNo,
                                       Business = systemBusiness,
                                       Code = 494,
                                       Balance = 0,
                                       IsSystemAccount = true,
                                       IsDefaultAccount = true,
                                       Name = "Travel - International",
                                       Description = "Expenses incurred from international travel which has a business purpose",
                                       TaxReturnPercent = 0
                                   };

            var coaOfficeFA = new ChartofAccount
                                  {
                                      Id = 201,
                                      AccountType = fixedAssertAccountType,
                                      TaxRate = tr15E,
                                      Business = systemBusiness,
                                      Code = 710,
                                      Balance = 0,
                                      IsSystemAccount = true,
                                      IsDefaultAccount = true,
                                      Name = "Office Equipment",
                                      Description = "Office equipment that is owned and controlled by the business",
                                      TaxReturnPercent = 0
                                  };
            var coaComputerFA = new ChartofAccount
                                    {
                                        Id = 202,
                                        AccountType = fixedAssertAccountType,
                                        TaxRate = tr15E,
                                        Business = systemBusiness,
                                        Code = 720,
                                        Balance = 0,
                                        IsSystemAccount = true,
                                        IsDefaultAccount = true,
                                        Name = "Computer Equipment",
                                        Description = "Computer equipment that is owned and controlled by the business",
                                        TaxReturnPercent = 0
                                    };

            context.ChartofAccounts.AddOrUpdate(
                coaAds,
                coaComputerFA,
                coaDepre,
                coaEntertainment,
                coaGeneral,
                coaInsurance,
                coaInterestIncome,
                coaLPH,
                coaOffice,
                coaOfficeFA,
                coaOtherRevenue,
                coaPhone,
                coaRent,
                coaRepairs,
                coaSales,
                coaTravelI,
                coaTravelN,
                coaVehicle
                );
        }

        #region help methods
        private void CreateIndeies(ReceiptsDbContext context)
        {
            CreateIndex(context, "Business", "BusinessName");
            CreateIndex(context, "Business", "GstNumber");
            CreateIndex(context, "ChartofAccountAccountType", "Name");
            CreateIndex(context, "ChartofAccountCategory", "Name");
            CreateIndex(context, "Client", "Username");
            CreateIndex(context, "Contact", "Name");
            CreateIndex(context, "Contact", "GstNumber");
        }        
        
        private const string CreateIndexQueryTemplate = "IF NOT EXISTS (SELECT name FROM sysindexes WHERE name = '{0}') CREATE {1} INDEX {0} ON {2} ({3})";
           
        private void CreateIndex(ReceiptsDbContext context, string table, string field, bool isUnique = true)
        {
            string indexName = isUnique ? "IX_Unique_" + table + "_" + field : "IX_" + table + "_" + field;
            string query = string.Format(CreateIndexQueryTemplate, indexName, isUnique ? "UNIQUE" : string.Empty,
                                         table, field);
            context.Database.ExecuteSqlCommand(query);
        }
        #endregion
    }
}
